﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using Skyhook.Core.Input;
using Skyhook.Core.Configuration;

namespace Skyhook.Core
{
    public class ApplicationComponent
    {
        public virtual Application Root {get; protected set;}
        public virtual ApplicationComponent Owner { get; protected set; }
        public virtual DataStorage Data { get; protected set; }

        List<ApplicationComponent> Children = new List<ApplicationComponent>();

        public bool IsInitialized {get; private set;}
        public bool IsContentLoaded { get; private set; }

        public ApplicationComponent()
        {
            Root = null;
            Owner = null;
            Data = null;

            IsInitialized = false;
            IsContentLoaded = false;
        }

        internal void LoadContentWithComponents()
        {
            LoadContent();

            foreach (ApplicationComponent component in Children)
            {
                component.LoadContentWithComponents();
            }

            IsContentLoaded = true;
        }
        protected virtual void LoadContent()
        {
        }

        internal void UnloadContentWithComponents()
        {
            foreach (ApplicationComponent component in Children)
            {
                component.UnloadContentWithComponents();
            }

            UnloadContent();

            IsContentLoaded = false;
        }
        protected virtual void UnloadContent()
        {
        }

        internal void InitializeWithComponents()
        {
            Initialize();

            foreach (ApplicationComponent component in Children)
            {
                component.InitializeWithComponents();
            }

            IsInitialized = true;
        }
        protected virtual void Initialize()
        {
        }

        internal virtual void UpdateWithComponents(GameTime time)
        {
            Update(time);

            foreach (ApplicationComponent component in Children)
            {
                component.UpdateWithComponents(time);
            }
        }
        protected virtual void Update(GameTime time)
        {  
        }

        internal virtual void DrawWithComponents(GameTime time)
        {
            Draw(time);

            foreach (ApplicationComponent component in Children)
            {
                component.DrawWithComponents(time);
            }
        }
        protected virtual void Draw(GameTime time)
        {
        }

        public virtual void AddChild(ApplicationComponent component)
        {
            Children.Add(component);

            if (IsInitialized)
            {
                component.InitializeWithComponents();
            }

            if (IsContentLoaded)
            {
                component.LoadContentWithComponents();
            }

            component.Root = Root;
            component.Owner = this;
            component.Data = Data;
        }

        public virtual void RemoveChild(ApplicationComponent component)
        {
            Children.Remove(component);

            if (IsContentLoaded)
            {
                component.UnloadContentWithComponents();
            }

            component.Root = null;
            component.Owner = null;
            component.Data = null;
        }
    }
}
